{extend name="user/base" /} {block name="main"}
<script src="__CDN__/static/js/captcha.js"></script>
<div id="app">
  <el-row class="frontend-footer-brother" justify="center">
    <el-col class="user-layouts" :span="16" :xs="24">
      {include file="user/left" /}
      <el-main class="layout-main">
        <div class="user-views">
          <el-card class="user-views-card" shadow="hover">
            <template #header>
              <div class="card-header">
                <span>{:__('personal data')}</span>
                <a
                  href="{:url('/account/changePassword')}"
                  class="el-button el-button--info is-plain"
                >
                  {:__('Change Password')}
                </a>
              </div>
            </template>
            <div class="user-profile">
              <el-form
                :model="state.form"
                :rules="state.rules"
                :label-width="100"
                ref="formRef"
                @keyup.enter="onSubmit()"
              >
                <el-form-item label="{:__('head portrait')}">
                  <el-upload
                    class="avatar-uploader"
                    :action="Config.siteConfig.uploadUrl"
                    :show-file-list="false"
                    :on-success="handleAvatarSuccess"
                    :before-upload="beforeAvatarUpload"
                  >
                    <img
                      v-if="state.form.avatar"
                      :src="state.form.avatar"
                      class="avatar"
                    />
                    <el-icon v-else class="avatar-uploader-icon">
                      <Plus />
                    </el-icon>
                  </el-upload>
                </el-form-item>
                <el-form-item
                  label="{:__('User name')}"
                  type="string"
                  v-model="state.form.username"
                  placeholder="{:__('Please input field')} {:__('User name')}"
                  prop="username"
                >
                  <el-input
                    v-model="state.form.username"
                    placeholder="{:__('Please input field')} {:__('User name')}"
                  />
                </el-form-item>
                <el-form-item
                  label="{:__('User nickname')}"
                  type="string"
                  v-model="state.form.nickname"
                  placeholder="{:__('Please input field')} {:__('User nickname') }"
                  prop="nickname"
                >
                  <el-input
                    v-model="state.form.nickname"
                    placeholder="{:__('Please input field')} {:__('User nickname') }"
                  />
                </el-form-item>
                <el-form-item
                  v-if="state.accountVerificationType.includes('email')"
                  label="{:__('email')}"
                >
                  <el-input
                    v-model="state.form.email"
                    readonly
                    placeholder="{:__('Operation via right button')}"
                  >
                    <template #append>
                      <el-button
                        type="primary"
                        @click="onChangeBindInfo('email')"
                      >
                        <!-- prettier-ignore -->
                        {{ state.form.email ? '{:__("Click Modify")}':'{:__("bind")}'}}
                      </el-button>
                    </template>
                  </el-input>
                </el-form-item>
                <el-form-item
                  v-if="state.accountVerificationType.includes('mobile')"
                  label="{:__('mobile')}"
                >
                  <el-input
                    v-model="state.form.mobile"
                    readonly
                    placeholder="{:__('Operation via right button')}"
                  >
                    <template #append>
                      <el-button
                        type="primary"
                        @click="onChangeBindInfo('mobile')"
                      >
                        {{ state.form.mobile ? '{:__("Click Modify")}' :
                        '{:__("profile.bind")}' }}
                      </el-button>
                    </template>
                  </el-input>
                </el-form-item>
                <el-form-item label="{:__('Gender')}">
                  <el-radio-group v-model="state.form.gender">
                    <el-radio :label="0" border>{:__('secrecy')}</el-radio>
                    <el-radio :label="1" border>{:__('male')}</el-radio>
                    <el-radio :label="2" border>{:__('female')}</el-radio>
                  </el-radio-group>
                </el-form-item>
                <el-form-item
                  label="{:__('birthday')}"
                  type="date"
                  v-model="state.form.birthday"
                >
                  <el-date-picker
                    v-model="state.form.birthday"
                    type="date"
                    placeholder="{:__('Please select')} {:__('birthday')}"
                  />
                </el-form-item>
                <el-form-item
                  label="{:__('Personal signature')}"
                  type="textarea"
                  placeholder="{:__('Please input field')} {:__('Personal signature') }"
                  v-model="state.form.motto"
                >
                  <el-input
                    v-model="state.form.motto"
                    placeholder="{:__('Please input field')} {:__('Personal signature') }"
                    show-word-limit
                    type="textarea"
                    :rows="3"
                    maxlength="120"
                  />
                </el-form-item>

                <el-form-item class="submit-buttons">
                  <el-button @click="onResetForm(formRef)">
                    {:__('Reset')}
                  </el-button>
                  <el-button
                    type="primary"
                    :loading="state.formSubmitLoading"
                    @click="onSubmit()"
                  >
                    {:__('Save')}
                  </el-button>
                </el-form-item>
              </el-form>
            </div>
          </el-card>

          <!-- 账户验证 -->
          <el-dialog
            title="{:__('Account verification')}"
            v-model="state.dialog.verification.show"
            class="ba-change-bind-dialog ba-verification-dialog"
            :destroy-on-close="true"
            :close-on-click-modal="false"
            width="30%"
          >
            <el-form
              :model="state.dialog.verification.form"
              :rules="state.dialog.verification.rules"
              :label-position="'top'"
              ref="verificationFormRef"
              @keyup.enter="onSubmitVerification()"
            >
              <el-form-item
                label="{:__('Account password verification')}"
                prop="password"
              >
                <el-input
                  type="password"
                  show-password
                  v-model="state.dialog.verification.form.password"
                  placeholder="{:__('Please input field')}{:__('password') }"
                ></el-input>
              </el-form-item>

              <el-form-item prop="captcha">
                <template #label>
                  <span v-if="state.dialog.type == 'email'">
                    {:__('Mail verification')}{:__('accept')}{:__('mail')}
                  </span>
                  <span v-else>
                    {:__('SMS verification')}{:__('accept')}{:__('mobile')}
                  </span>
                </template>
                <el-row style="width: 100%" :gutter="10">
                  <el-col :span="18">
                    <el-input
                      v-model="state.dialog.verification.form.captcha"
                      placeholder="{:__('Please input field')}{:__('Verification Code')}"
                      autocomplete="off"
                    />
                  </el-col>
                  <el-col class="captcha-box" :span="6">
                    <el-button
                      @click="sendVerificationCaptchaPre"
                      :loading="state.dialog.sendCaptchaLoading"
                      :disabled="state.dialog.codeSendCountdown <= 0 ? false : true"
                      type="primary"
                      style="width: 100%"
                    >
                      {{ state.dialog.codeSendCountdown <= 0 ? "{:__('send')}" :
                      state.dialog.codeSendCountdown + '{:__("seconds")}' }}
                    </el-button>
                  </el-col>
                </el-row>
              </el-form-item>
            </el-form>
            <template #footer>
              <div :style="'width: calc(100% - 20px)'">
                <el-button @click="state.dialog.verification.show = false">
                  {:__('Cancel')}
                </el-button>
                <el-button
                  v-blur
                  :loading="state.dialog.submitLoading"
                  @click="onSubmitVerification()"
                  type="primary"
                >
                  {:__('next step') }
                </el-button>
              </div>
            </template>
          </el-dialog>

          <!-- 绑定 -->
          <el-dialog
            title="{:__('bind')}{:__('profile')}"
            v-model="state.dialog.bind.show"
            class="ba-change-bind-dialog ba-bind-dialog"
            :destroy-on-close="true"
            :close-on-click-modal="false"
            width="30%"
          >
            <el-form
              :model="state.dialog.bind.form"
              :rules="state.dialog.bind.rules"
              :label-position="'top'"
              ref="bindFormRef"
              @keyup.enter="onSubmitBind()"
            >
              <el-form-item
                label="{:__('Account password verification')}"
                v-if="!state.dialog.verification.accountVerificationToken"
                prop="password"
              >
                <el-input
                  type="password"
                  v-model="state.dialog.bind.form.password"
                  showPassword
                  placeholder="{:__('Please input field')}{:__('password') }"
                ></el-input>
              </el-form-item>

              <el-form-item
                v-if="state.dialog.type == 'email'"
                label="{:__('New email')}"
                prop="email"
              >
                <el-input
                  type="string"
                  v-model="state.dialog.bind.form.email"
                  placeholder="{:__('Please input field')}{:__('New email')}"
                />
              </el-form-item>
              <el-form-item
                v-if="state.dialog.type == 'mobile'"
                label="{:__('New mobile')}"
                prop="mobile"
              >
                <el-input
                  type="string"
                  v-model="state.dialog.bind.form.mobile"
                  placeholder="{:__('Please input field')}{:__('New mobile')}"
                />
              </el-form-item>
              <el-form-item
                :label="state.dialog.type == 'email' ? '{:__('Mail verification')}' : '{:__('SMS verification')}'"
                prop="captcha"
              >
                <el-row style="width: 100%" :gutter="10">
                  <el-col :span="18">
                    <el-input
                      v-model="state.dialog.bind.form.captcha"
                      placeholder="{:__('Please input field')} {:__('Verification Code') }"
                      autocomplete="off"
                    />
                  </el-col>
                  <el-col class="captcha-box" :span="6">
                    <el-button
                      @click="sendBindCaptchaPre"
                      :loading="state.dialog.sendCaptchaLoading"
                      :disabled="state.dialog.codeSendCountdown <= 0 ? false : true"
                      type="primary"
                      style="width: 100%"
                    >
                      {{ state.dialog.codeSendCountdown <= 0 ? "{:__('send')}" :
                      state.dialog.codeSendCountdown + '{:__("seconds")}' }}
                    </el-button>
                  </el-col>
                </el-row>
              </el-form-item>
            </el-form>
            <template #footer>
              <div :style="'width: calc(100% - 20px)'">
                <el-button @click="state.dialog.bind.show = false">
                  {:__('Cancel')}
                </el-button>
                <el-button
                  v-blur
                  :loading="state.dialog.submitLoading"
                  @click="onSubmitBind()"
                  type="primary"
                >
                  {:__('bind') }
                </el-button>
              </div>
            </template>
          </el-dialog>
        </div>
      </el-main>
    </el-col>
  </el-row>
</div>

<script>
  const App = {
    setup() {
      const { ref, reactive, resolveComponent, createVNode, render } = Vue;

      function validatorPassword(rule, val, callback) {
        if (!val) {
          return callback();
        }
        if (!/^(?!.*[&<>"'\n\r]).{6,32}$/.test(val)) {
          return callback(
            new Error("{:__('Please enter the correct password')}")
          );
        }
        return callback();
      }

      function validatorAccount(rule, val, callback) {
        if (!val) {
          return callback();
        }
        if (!/^[a-zA-Z][a-zA-Z0-9_]{2,15}$/.test(val)) {
          return callback(
            new Error("{:__('Please enter the correct account')}")
          );
        }
        return callback();
      }

      function validatorMobile(rule, mobile, callback) {
        // 允许空值，若需必填请添加多验证规则
        if (!mobile) {
          return callback();
        }
        if (!/^(1[3-9])\d{9}$/.test(mobile.toString())) {
          return callback(
            new Error("{:__('Please enter the correct mobile number')}")
          );
        }
        return callback();
      }

      const formRef = ref(null);
      const bindFormRef = ref();
      const verificationFormRef = ref();
      const user = Config.user;
      const state = reactive({
        formSubmitLoading: false,
        form: Config.user,
        rules: {
          username: [
            {
              required: true,
              message: '{:__("Please input field")}{:__("User name")}',
              trigger: "blur",
            },
            { validator: validatorAccount, trigger: "blur" },
          ],
          nickname: [
            {
              required: true,
              message: '{:__("Please input field")}{:__("nickname")}',
              trigger: "blur",
            },
          ],
        },
        // prettier-ignore
        accountVerificationType: '{$accountVerificationType|raw}',
        dialog: {
          type: "email",
          submitLoading: false,
          sendCaptchaLoading: false,
          codeSendCountdown: 0,
          captchaId: Config.uuid,
          verification: {
            show: false,
            rules: {
              password: [
                {
                  required: true,
                  message: '{:__("Please input field")}{:__("password")}',
                  trigger: "blur",
                },
                { validator: validatorPassword, trigger: "blur" },
              ],
              captcha: [
                {
                  required: true,
                  message:
                    '{:__("Please input field")}{:__("Verification Code")}',
                  trigger: "blur",
                },
              ],
            },
            form: {
              password: "",
              captcha: "",
            },
            accountVerificationToken: "",
          },
          bind: {
            show: false,
            rules: {
              password: [
                {
                  required: true,
                  message: '{:__("Please input field")}{:__("password")}',
                  trigger: "blur",
                },
                { validator: validatorPassword, trigger: "blur" },
              ],
              email: [
                {
                  required: true,
                  message: '{:__("Please input field")}{:__("email")}',
                  trigger: "blur",
                },
                { type: "email", trigger: "blur" },
              ],
              mobile: [
                {
                  required: true,
                  message: '{:__("Please input field")}{:__("mobile")}',
                  trigger: "blur",
                },
                { validator: validatorMobile, trigger: "blur" },
              ],
              captcha: [
                {
                  required: true,
                  message:
                    '{:__("Please input field")}{:__("Verification Code")}',
                  trigger: "blur",
                },
              ],
            },
            form: {
              password: "",
              email: "",
              mobile: "",
              captcha: "",
            },
          },
        },
      });

      const startTiming = (seconds) => {
        state.dialog.codeSendCountdown = seconds;
        timer = window.setInterval(() => {
          state.dialog.codeSendCountdown--;
          if (state.dialog.codeSendCountdown <= 0) {
            endTiming();
          }
        }, 1000);
      };
      const endTiming = () => {
        state.dialog.codeSendCountdown = 0;
        clearInterval(timer);
      };

      const onChangeBindInfo = (type) => {
        if (
          (type == "email" && user.email) ||
          (type == "mobile" && user.mobile)
        ) {
          state.dialog.verification.show = true;
        } else {
          state.dialog.bind.show = true;
        }
        state.dialog.type = type;
      };

      /**
       * 弹出点击验证码
       * @param uuid 开发者自定义的唯一标识
       * @param callback 验证成功的回调，业务接口可通过 captchaInfo 进行二次验证
       * @param options
       */
      const clickCaptcha = (uuid, callback, options = {}) => {
        // const component = resolveComponent(Captcha);
        let vnode = createVNode(Captcha, {
          uuid,
          callback,
          ...options,
          key: shortUuid(),
        });

        render(vnode, document.body);
        vnode = null;
      };

      const sendVerificationCaptchaPre = () => {
        if (state.dialog.codeSendCountdown > 0) return;
        verificationFormRef.value.validateField("password").then((res) => {
          if (!res) return;
          clickCaptcha(state.dialog.captchaId, (captchaInfo) =>
            sendVerificationCaptcha(captchaInfo)
          );
        });
      };
      const sendVerificationCaptcha = (captchaInfo) => {
        state.dialog.sendCaptchaLoading = true;
        const func = state.dialog.type == "email" ? sendEms : sendSms;
        func(user[state.dialog.type], `user_${state.dialog.type}_verify`, {
          password: state.dialog.verification.form.password,
          captchaId: state.dialog.captchaId,
          captchaInfo,
        })
          .then((res) => {
            if (res.code == 1) startTiming(60);
          })
          .finally(() => {
            state.dialog.sendCaptchaLoading = false;
          });
      };

      const sendBindCaptchaPre = () => {
        if (state.dialog.codeSendCountdown > 0) return;
        bindFormRef.value.validateField(state.dialog.type).then((res) => {
          if (!res) return;
          clickCaptcha(state.dialog.captchaId, (captchaInfo) =>
            sendBindCaptcha(captchaInfo)
          );
        });
      };
      const sendBindCaptcha = (captchaInfo) => {
        state.dialog.sendCaptchaLoading = true;
        const func = state.dialog.type == "email" ? sendEms : sendSms;
        func(
          state.dialog.bind.form[state.dialog.type],
          `user_change_${state.dialog.type}`,
          {
            captchaId: state.dialog.captchaId,
            captchaInfo,
          }
        )
          .then((res) => {
            if (res.code == 1) startTiming(60);
          })
          .finally(() => {
            state.dialog.sendCaptchaLoading = false;
          });
      };

      const onSubmitVerification = () => {
        if (!verificationFormRef.value) return;
        verificationFormRef.value.validate((res) => {
          if (res) {
            state.dialog.submitLoading = true;
            postVerification({
              type: state.dialog.type,
              captcha: state.dialog.verification.form.captcha,
            })
              .then((res) => {
                endTiming();
                state.dialog.bind.show = true;
                state.dialog.type = res.data.type;
                state.dialog.verification.show = false;
                state.dialog.verification.accountVerificationToken =
                  res.data.accountVerificationToken;
              })
              .finally(() => {
                state.dialog.submitLoading = false;
              });
          }
        });
      };

      const onSubmitBind = () => {
        if (!bindFormRef.value) return;
        bindFormRef.value.validate((res) => {
          if (res) {
            state.dialog.submitLoading = true;
            postChangeBind({
              type: state.dialog.type,
              accountVerificationToken:
                state.dialog.verification.accountVerificationToken,
              ...state.dialog.bind.form,
            })
              .then(() => {
                endTiming();
                state.dialog.bind.show = false;
                user[state.dialog.type] =
                  state.dialog.bind.form[state.dialog.type];
              })
              .finally(() => {
                state.dialog.submitLoading = false;
              });
          }
        });
      };

      const onResetForm = (formEl) => {
        if (!formEl) return;
        formEl.resetFields && formEl.resetFields();
      };

      const onSubmit = () => {
        if (!formRef.value) return;
        formRef.value.validate((valid) => {
          if (valid) {
            state.formSubmitLoading = true;
            createAxios(
              {
                url: "/account/profile",
                method: "POST",
                data: state.form,
              },
              {
                showSuccessMessage: true,
              }
            )
              .then(() => {
                state.formSubmitLoading = false;
                setTimeout(() => {
                  location.reload();
                }, 1000);
              })
              .catch(() => {
                state.formSubmitLoading = false;
              });
          }
        });
      };

      const handleAvatarSuccess = (response, uploadFile) => {
        state.form.avatar = response.data.file.url;
      };

      const beforeAvatarUpload = (rawFile) => {
        let errorMsg = "";
        if (!rawFile.name || typeof rawFile.size == "undefined") {
          errorMsg = __("The data of the uploaded file is incomplete!");
        } else if (!checkFileMimetype(rawFile.name, rawFile.type)) {
          errorMsg = __("The type of uploaded file is not allowed!");
        } else if (rawFile.size > Config.siteConfig.upload.maxSize) {
          errorMsg = __(
            "The size of the uploaded file exceeds the allowed range!"
          );
        }

        if (errorMsg) {
          ElNotification({
            type: "error",
            message: errorMsg,
            zIndex: 9999,
          });
          return false;
        }

        return true;
      };
      console.log(state);

      return {
        Config,
        state,
        formRef,
        bindFormRef,
        verificationFormRef,
        onChangeBindInfo,
        onSubmit,
        onResetForm,
        handleAvatarSuccess,
        beforeAvatarUpload,
        onSubmitVerification,
        onSubmitBind,
        sendVerificationCaptchaPre,
        sendBindCaptchaPre,
      };
    },
  };
  const app = Vue.createApp(App);

  app.use(ElementPlus, { locale: ElementPlusLocaleZhCn });
  app.mount("#app");
</script>
{/block}
